package com.v3admin.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.v3admin.common.service.IServiceImpl;
import com.v3admin.system.domain.SystemMenu;
import com.v3admin.system.mapper.SystemMenuMapper;
import com.v3admin.system.service.SystemMenuService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 系统菜单
 *
 * @author Junpeng.Li
 * @date 2023-12-15 16:34
 */
@Service
public class SystemMenuServiceImpl extends IServiceImpl<SystemMenuMapper, SystemMenu>
        implements SystemMenuService {

    @Override
    public boolean save(SystemMenu entity) {
        // 添加默认值
        if (null == entity.getPid()) {
            entity.setPid(SystemMenu.TOP_PID);
        }
        if (null == entity.getNewTabOpen()) {
            entity.setNewTabOpen(false);
        }
        entity.setEnable(true);

        return super.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Serializable id) {
        boolean b = super.removeById(id);

        // 查找并删除所有子菜单
        List<SystemMenu> childMenus = this.findByPidDeep((Long) id);
        if (CollUtil.isNotEmpty(childMenus)) {
            Set<Long> tempIds = extractIds(childMenus);
            super.removeBatchByIds(tempIds);
        }

        return b;
    }

    @Override
    public List<SystemMenu> findByPid(Long pid) {
        QueryWrapper<SystemMenu> wrapper = queryWrapper(wrap -> wrap.eq(SystemMenu.TBF_PID, pid));
        return super.list(wrapper);
    }

    @Override
    public List<SystemMenu> findByPidDeep(Long pid) {
        List<SystemMenu> children = this.findByPid(pid);

        // 递归查询子菜单
        if (CollUtil.isNotEmpty(children)) {
            children.forEach(child -> {
                List<SystemMenu> tempChildren = this.findByPidDeep(child.getId());
                child.setChildren(tempChildren);
            });
        }

        return children;
    }

    @Override
    public List<SystemMenu> toTree(List<SystemMenu> menus) {
        final String key = "origin";
        // 构建树
        List<Tree<Long>> treeNodes = TreeUtil.build(menus, SystemMenu.TOP_PID, (node, tree) -> {
            tree.setId(node.getId());
            tree.setParentId(node.getPid());
            tree.setWeight(node.getOrder());
            tree.setName(node.getName());
            tree.putExtra(key, node);
        });

        // 转换成SystemMenu对象集合
        List<SystemMenu> treeMenus = toMenuObj(treeNodes, key);
        return CollUtil.emptyIfNull(treeMenus);
    }

    /**
     * 递归解析子菜单，并设置到对应的SystemMenu对象的children字段中
     *
     * @param treeChild 子树的集合
     * @param key       标识源数据的key
     * @return 菜单集合
     */
    @SuppressWarnings("all")
    private List<SystemMenu> toMenuObj(List<Tree<Long>> treeChild, final String key) {
        if (CollUtil.isEmpty(treeChild)) {
            return null;
        }

        List<SystemMenu> children = new ArrayList<>(treeChild.size());
        treeChild.forEach(item -> {
            SystemMenu menu = (SystemMenu) item.get(key);
            menu.setChildren(toMenuObj(item.getChildren(), key));
            children.add(menu);
        });
        return children;
    }

    /**
     * 提取菜单的ID
     *
     * @param menus 菜单集合
     * @return 菜单ID的集合
     */
    private Set<Long> extractIds(List<SystemMenu> menus) {
        Set<Long> ids = new HashSet<>();
        menus.forEach(menu -> {
            ids.add(menu.getId());

            if (CollUtil.isNotEmpty(menu.getChildren())) {
                Set<Long> childIds = extractIds(menu.getChildren());
                ids.addAll(childIds);
            }
        });
        return ids;
    }
}
